package com.pan.download5.search;

import com.pan.crawler.Search;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

public class ConsoleSearchDriver implements SearchDriver {

    private List<Search> searchList;

    public ConsoleSearchDriver(Class<? extends Search>[] searchClasses) {
        searchList = new ArrayList<>();
        List<FutureTask<Search>> futureTaskList = new ArrayList<>();
        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(10, 10, 114514, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(10));
        CountDownLatch countDownLatch = new CountDownLatch(searchClasses.length);
        for (Class<? extends Search> searchClass : searchClasses) {
            Constructor<? extends Search> constructor = null;
            try {
                constructor = searchClass.getConstructor();
            } catch (NoSuchMethodException e) {
                throw new RuntimeException(e);
            }
            Constructor<? extends Search> finalConstructor = constructor;
            FutureTask<Search> futureTask = new FutureTask<>(()-> {
                try {
                    Search search = finalConstructor.newInstance();
                    return search;
                }finally {
                    countDownLatch.countDown();
                }
            });
            futureTaskList.add(futureTask);
            poolExecutor.execute(futureTask);
        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        poolExecutor.shutdown();
        for (FutureTask<Search> futureTask : futureTaskList) {
            Search search = null;
            try {
                search = futureTask.get();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } catch (ExecutionException e) {
                throw new RuntimeException(e);
            }
            if (search != null){
                searchList.add(search);
            }
        }
    }

    private void readConsoleAndSearch() throws IOException {
        byte[] buf = new byte[1024];
        while (true) {
            String searchContent = null;
            for (int i = 0; ; i++) {
                int b =  System.in.read();
                if (b == 10) {
                    searchContent = new String(buf,0,i).trim();
                    break;
                }
                buf[i] = (byte) b;
            }
            if (searchContent.equals("quit")) break;
            else if (searchContent.length() == 0) continue;
            for (Search search : searchList) {
                search.find(searchContent);
            }
            System.out.println("---------------------------");
            System.out.println("搜索 "+searchContent+" 完成！");
            System.out.println("---------------------------");
        }
    }
    @Override
    public void run() {
        System.out.println("------------提示------------");
        System.out.println("搜索：控制台输入搜索内容 按enter");
        System.out.println("退出：控制台输入 quit 按enter");
        System.out.println("---------------------------");

        try {
            readConsoleAndSearch();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
